package com.guaoran.source.zookeeper.common;

import com.guaoran.source.zookeeper.config.ZookeeperConfig;
import com.guaoran.source.zookeeper.loadbalance.LoadBalanceServer;
import com.guaoran.source.zookeeper.loadbalance.RandomLoadBalanceService;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : 孤傲然
 * @Description :
 * @date :2018/6/14 13:48
 */
public class DiscoveryServiceImpl implements DiscoveryService {
    private CuratorFramework curatorFramework = ZookeeperConfig.initCuratorFramework();
    private List<String> serviceList = new ArrayList<>();
    @Override
    public String discoveryService(String serviceName) {
        serviceName = "/" + serviceName;
        try {
            if(curatorFramework.checkExists().forPath(serviceName) == null){
                throw new RuntimeException("服务名称对应的节点不存在"+serviceName);
            }
            serviceList = curatorFramework.getChildren().forPath(serviceName);
            //监听子节点，当子节点发生变化时将会重新赋值
            pathChildrenWatcher(serviceName);
            //负载均衡获得子节点去调用
            LoadBalanceServer loadBalanceServer = new RandomLoadBalanceService();
            return loadBalanceServer.selectServer(serviceList);
        } catch (Exception e) {
            throw new RuntimeException("获取服务失败"+serviceName+":"+e);
        }
    }

    /**
     * 监听该节点下的子节点的增删改操作
     * @param path
     */
    private void pathChildrenWatcher(String path){
        PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework,path,true);
        PathChildrenCacheListener listener = new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                serviceList = client.getChildren().forPath(path);
            }
        };
        pathChildrenCache.getListenable().addListener(listener);
        try {
            pathChildrenCache.start();
        } catch (Exception e) {
            throw new RuntimeException("监听子节点失败："+path+":"+e);
        }
    }
}
